home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / wf_draw.pro < prev    next >
Text File  |  1997-07-08  |  8KB  |  244 lines

  1. ; $Id: wf_draw.pro,v 1.5 1997/01/15 03:11:50 ali Exp $
  2. ;
  3. ; Copyright (c) 1993-1997, Research Systems, Inc.  All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;    WF_DRAW
  8. ;
  9. ; PURPOSE:
  10. ;    This procedure draws weather fronts of various types with
  11. ;    spline smoothing.
  12. ;
  13. ; CATEGORY:
  14. ;    Meterology.
  15. ;
  16. ; CALLING SEQUENCE:
  17. ;    WF_DRAW, X, Y
  18. ;
  19. ; INPUTS:
  20. ;      X, Y:        Vectors of abcissae and ordinates defining the
  21. ;             front to be drawn.
  22. ;
  23. ; KEYWORD PARAMETERS:
  24. ;      COLD:         A cold front. The default is a plain line with
  25. ;             no annotations.
  26. ;      WARM:         A warm front.
  27. ;      OCCLUDED:    An occluded front.
  28. ;      STATIONARY:  A stationary front.
  29. ;      CONVERGENCE: A convergence line.
  30. ;      FRONT_TYPE:  Index of type of front to draw, COLD=1, WARM=2, etc.
  31. ;             Not required if plain line is desired or if an
  32. ;             explicit front type keyword is specified.
  33. ;      THICK:         Line thickness. The default = 1.0.
  34. ;      INTERVAL:    The spline interpolation interval, in normalized
  35. ;             units. The default = 0.01. Larger values give coarser
  36. ;             approximations to curves, smaller values make more
  37. ;             interpolted points.
  38. ;      COLOR:       The color to use. The default = !P.COLOR.
  39. ;      DEVICE:      If set, X and Y are in device coordinates.
  40. ;      DATA:        If set, X and Y are in data coordinates.
  41. ;      NORM:         If set, X and Y are in normalized coordinates.
  42. ;             This is the default.
  43. ;      PSYM:         If set, draw a marker (index = PSYM) on each actual
  44. ;             [X, Y] data point.
  45. ;      SYM_LEN:     The length and spacing factor for front symbols,
  46. ;             in normalized units. The default = 0.15.
  47. ;      SYM_HT:      The height of front symbols, in normalized units.
  48. ;             The default = 0.02.
  49. ;
  50. ; OUTPUTS:
  51. ;    No explicit outputs.
  52. ;
  53. ; SIDE EFFECTS:
  54. ;    Draws objects on current graphics device.
  55. ;
  56. ; PROCEDURE:
  57. ;    Uses parametric spline interpolation to smooth the lines.
  58. ;    POLYFILL is used to make the annotations on the front lines.
  59. ;
  60. ; EXAMPLE:
  61. ;    Draw a front given 3 points:
  62. ;      WF_DRAW, [40, 20, 40], [30, 40, 25], /DATA, /COLD
  63. ;
  64. ; MODIFICATION HISTORY:
  65. ;    DMS, RSI.   August, 1993.  Written.
  66. ;-
  67.  
  68.  
  69. PRO SPLINE_INTERP, x, y, xp, yp, INTERVAL=interval, TORIG = t, TSPLINE=tt
  70. ; Interpolate the points X[i],Y[i] using cubic spline interpolation,
  71. ;    returning the result in xp, yp.
  72. ; Try to make the distance between the resulting points
  73. ; approximately equal to INTERVAL.
  74.  
  75.  
  76.     ;Basic interval, in normalized coords.
  77. if N_ELEMENTS(interval) le 0 then interval = .01
  78. n = n_elements(x)
  79. t = sqrt((x-shift(x,1))^2 + (y-shift(y,1))^2)    ;Parametric variable
  80. t[0] = 0.0
  81. r = ceil(t/interval)        ;# of pnts for each interv
  82. tt = fltarr(total(r)+1, /nozero)
  83. j = 0L
  84. for i=1, n-1 do begin        ;Each interval
  85.     k = long(r[i])        ;# of points in this interval
  86.     tt[j] = findgen(k)*(t[i]/k) + t[i-1]  ;Parameteric variable
  87.     t[i] = t[i] + t[i-1]    ;Cumulative t value
  88.     j = j + k
  89.     endfor
  90. tt[j] = t[n-1]            ;Last t.
  91. xp = SPLINE(t,x,tt)        ;Now use SPLINE function
  92. yp = SPLINE(t,y,tt)
  93. end
  94.  
  95.  
  96.  
  97. pro wf_draw, x, y, FRONT_TYPE = pat, COLD=cold, WARM=warm, $
  98.     OCCLUDED=occluded, STATIONARY=stationary, $
  99.     CONVERGENCE=CONVERGENCE, THICK=thick, INTERVAL=interval, $
  100.     COLOR = c, DEVICE = device, DATA = data, NORMAL = normal, $
  101.     PSYM = psym, SYM_LEN = slen, SYM_HT = sht
  102. ;
  103.  
  104. if n_elements(interval) le 0 then interval = 0.01    ;Default norm interval
  105. if n_elements(c) eq 0 then c = !p.color
  106. if n_elements(thick) eq 0 then thick = 0.0
  107.  
  108. if n_elements(pat) le 0 then pat = 0    ;Default pattern = none
  109. if keyword_set(COLD) then pat = 1 else $
  110. if keyword_set(warm) then pat = 2 else $
  111. if keyword_set(occluded) then pat = 3 else $
  112. if keyword_set(stationary) then pat = 4 else $
  113. if keyword_set(convergence) then pat = 5
  114.  
  115. if keyword_set(data) then xp = convert_coord(x,y,/data, /to_norm) $
  116. else if keyword_set(device) then xp = convert_coord(x,y,/device, /to_norm) $
  117. else xp = convert_coord(x,y,/norm, /to_norm)
  118.  
  119. if n_elements(x) gt 2 then $    ;Enough to interpolate?
  120.     spline_interp, xp[0,*], xp[1,*], xs, ys, INTERVAL=interval $
  121. else begin
  122.     xs = xp[0,*]
  123.     ys = xp[1,*]
  124. endelse
  125.  
  126.  
  127. ;    Length of basic pattern in normalized units.
  128. if n_elements(slen) le 0 then patlen = 0.15 else patlen = slen
  129. ;    Pattern height (distance from line)
  130. if n_elements(sht) le 0 then sht = 0.02
  131.  
  132. PLOTS, xs, ys, thick=thick, COLOR = c, /NORM    ;Draw basic line.
  133.  
  134. pxt = [0, .2, .4]    ;Triangle pattern, occupies .4 of each pattern interval
  135. pyt = [0, 1., 0.]
  136.             ;half-circle pattern
  137. pxc = [ 0.00, 0.0666667, 0.133333, 0.200, 0.266667, 0.333333,  0.400] ;t
  138. pyc = [ 0.0, 0.50,  0.866,  1.0, 0.866, 0.5, 0.]    ;Approx sin(t)
  139.  
  140. case pat of
  141. 1:   BEGIN            ;Cold = triangles
  142.     px = pxt * patlen
  143.     py = pyt * sht
  144.     goto, draw_polys
  145.     ENDCASE
  146. 2:   BEGIN            ;Warm = half circles.
  147.     px = pxc * patlen
  148.     py = pyc * sht
  149.     goto, draw_polys
  150.     ENDCASE
  151. 3:   BEGIN            ;occlud = alternate tris, circles, same side
  152.     px = [pxt, pxc + 0.45] * patlen
  153.     py = [pyt, pyc] * sht
  154.     goto, draw_polys
  155.     ENDCASE
  156. 4:   BEGIN            ;stationary = alt circ, triangs, alt sides
  157.     px = [pxt, pxc + 0.45] * patlen
  158.     py = [pyt, -pyc] * sht
  159.     goto, draw_polys
  160.     ENDCASE
  161. 5:   BEGIN            ;converg = hash marks
  162.     px = [0., .2, .25, .4] * patlen
  163.     py = [0,1,0,-1.] * sht
  164.     patlen = patlen / 2.    ;Half as long
  165.  
  166. draw_polys:
  167.     dx = xs[1:*]-xs        ;Dx(i) = x(i+1) - x(i)
  168.     dy = ys[1:*]-ys        ;Get derivatives
  169.     dt = sqrt(dx^2 + dy^2)    ;Distance between points
  170.     dx = dx / dt
  171.     dy = dy / dt
  172.     nt = n_elements(dt)
  173.     tt = fltarr(nt+1)    ;Cumulative distance
  174.     for i=1, nt do tt[i] = tt[i-1] + dt[i-1] ;cumulative t
  175.  
  176.     t = 0.0            ;Pattern start
  177.     l = 0L            ;Subscript in dx,dy,dt.
  178.     n = n_elements(px)
  179.     n2 = 2 * n
  180.     xp = fltarr(n2)        ;Vertices of polygons
  181.     yp = fltarr(n2)
  182.     tend = tt[nt]
  183.  
  184.     while t lt tend do begin
  185.         tx = t + px        ;Parameteric values
  186.         for i=0,n-1 do begin
  187.         if tx[i] ge tend then begin
  188.             x0 = xs[nt]
  189.             y0 = ys[nt]
  190.             xp[i] = x0
  191.             yp[i] = y0
  192.         endif else begin            
  193.             while tt[l] lt tx[i] do l=l+1L  ;Straddle
  194.             l1 = l-1L > 0L        ;tt[l1] < tx[i] <= tt[l]
  195.             p0 = (tx[i] - tt[l1])/dt[l1]    ;Interpol fract
  196.             x0 = xs[l1] + p0 * (xs[l] - xs[l1])  ;Point on front line
  197.             y0 = ys[l1] + p0 * (ys[l] - ys[l1])
  198.             xp[i] = x0 - py[i] * dy[l1]   ;Rotate 90 for symbol pnt
  199.             yp[i] = y0 + py[i] * dx[l1]
  200.             endelse
  201.         k = n2-i-1
  202.         xp[k] = x0        ;Baseline for return
  203.         yp[k] = y0
  204.         endfor
  205.         if pat eq 5 then begin    ;Special case for convergence
  206.         plots, xp[0:1], yp[0:1], color=c, thick=thick, /NORM
  207.         plots, xp[2:3], yp[2:3], color=c, thick=thick, /NORM
  208.         endif $
  209.         else polyfill, xp, yp, color=c, /NORM  ;Otherwise fill polygon
  210.         t = t + patlen
  211.     endwhile
  212.     ENDCASE        
  213. else: q=0
  214. endcase
  215.  
  216. if n_elements(psym) gt 0 then begin    ;Mark data points?
  217.     if n_elements(xp) gt 0 then PLOTS, xp, /NORM, PSYM=psym, COLOR=c $
  218.     else PLOTS, x,y, /NORM, PSYM=psym, COLOR=c
  219.     endif
  220. end
  221.  
  222.  
  223.  
  224. pro test_wf_draw
  225. map_set, limit = [25, -125, 50, -70], /grid, /usa
  226. wf_draw, [ -120, -110, -100], [30, 50, 45], /COLD, /DATA, THICK=2
  227. wf_draw, [ -80, -80, -75], [ 50, 40, 35], /WARM, /DATA, THICK=2
  228. wf_draw, [ -80, -80, -75]-10., [ 50, 40, 35], /OCCLUDED, /DATA, THICK=2
  229. wf_draw, [ -120, -105], [ 40,35], /STATION, /DATA, THICK=2
  230. wf_draw, [ -100, -90, -90], [ 30,35,40], /CONVERG, /DATA, THICK=2
  231.  
  232. names = ['None','Cold', 'Warm', 'Occluded', 'Stationary', 'Convergent']
  233. x = [.015, .30]
  234. y = 0.04
  235. dy = 0.05
  236. ty = n_elements(names) * dy + y
  237. polyfill, x[[0,1,1,0]], [0, 0, ty, ty], /NORM, color=!p.background
  238. for i=0, n_elements(names)-1 do begin
  239.     wf_draw, x, y, /NORM, FRONT_TYPE=i, THICK=2
  240.     xyouts, x[1]+0.015, y[0], names[i], /NORM, CHARS=1.5
  241.     y = y + dy
  242.     endfor
  243. end
  244.